package web.sms.mvc.controller.exception;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.ui.Model;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import web.sms.core.exception.ServiceException;
import web.sms.core.pojo.JsonInfo;
import web.sms.utils.HttpUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created by Eoly on 2017/4/7.
 * 总体异常处理
 */
@ControllerAdvice
public class ExceptionAdvice {

    private Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class);

    /**
     * 业务逻辑请求异常处理
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(ServiceException.class)
    public String handleServiceException(
            ServiceException e,
            HttpServletResponse response,
            HttpServletRequest request,
            Model model
    ) {
        JsonInfo jsonInfo = new JsonInfo(e.getError(), e.getMessage());
        if (HttpUtils.isAjaxRequestInternal(request)) {
            HttpUtils.sendJsonResultByCheckAjax(jsonInfo, request, response);
        }
        model.addAttribute("e", jsonInfo);
        logger.info("业务逻辑请求异常：" + e.getMessage(), e);
        return "error";
    }

    /**
     * 400 - Bad Request
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public String handleHttpMessageNotReadableException(
            HttpMessageNotReadableException e,
            HttpServletResponse response,
            HttpServletRequest request,
            Model model) {
        // logger.error("参数解析失败", e);
        JsonInfo jsonInfo = new JsonInfo(-1, e.getMessage());
        if (HttpUtils.isAjaxRequestInternal(request)) {
            HttpUtils.sendJsonResultByCheckAjax(jsonInfo, request, response);
        }
        model.addAttribute("e", jsonInfo);
        logger.info("请求异常：参数解析失败" + e.getMessage(), e);
        return "error";
    }

    /**
     * 405 - Method Not Allowed
     */
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public String handleHttpRequestMethodNotSupportedException(
            HttpRequestMethodNotSupportedException e,
            HttpServletResponse response,
            HttpServletRequest request,
            Model model) {
        // logger.error("不支持当前请求方法", e);
        JsonInfo jsonInfo = new JsonInfo(-1, e.getMessage());
        if (HttpUtils.isAjaxRequestInternal(request)) {
            HttpUtils.sendJsonResultByCheckAjax(jsonInfo, request, response);
        }
        model.addAttribute("e", jsonInfo);
        logger.info("请求异常：不支持当前请求方法" + e.getMessage(), e);
        return "error";
    }

    /**
     * 415 - Unsupported Media Type
     */
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public String handleHttpMediaTypeNotSupportedException(
            HttpMediaTypeNotSupportedException e,
            HttpServletResponse response,
            HttpServletRequest request,
            Model model) {
        // logger.error("不支持当前媒体类型", e);
        JsonInfo jsonInfo = new JsonInfo(-1, e.getMessage());
        if (HttpUtils.isAjaxRequestInternal(request)) {
            HttpUtils.sendJsonResultByCheckAjax(jsonInfo, request, response);
        }
        model.addAttribute("e", jsonInfo);
        logger.info("请求异常：不支持当前媒体类型" + e.getMessage(), e);
        return "error";
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(BindException.class)
    public String handleBindException(
            BindException e,
            HttpServletResponse response,
            HttpServletRequest request,
            Model model
    ) {
        // logger.error("绑定错误", e);
        JsonInfo jsonInfo = new JsonInfo(-1, "提交的信息中有一部分有误，系统不能识别");
        if (HttpUtils.isAjaxRequestInternal(request)) {
            HttpUtils.sendJsonResultByCheckAjax(jsonInfo, request, response);
        }
        model.addAttribute("e", jsonInfo);
        logger.info("请求异常：" + e.getMessage(), e);
        return "error";
    }
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public String handleMethodArgumentTypeMismatchException(
            MethodArgumentTypeMismatchException e,
            HttpServletResponse response,
            HttpServletRequest request,
            Model model
    ) {
        // logger.error("绑定错误", e);
        JsonInfo jsonInfo = new JsonInfo(-1, "提交的信息中有一部分有误，系统不能识别");
        if (HttpUtils.isAjaxRequestInternal(request)) {
            HttpUtils.sendJsonResultByCheckAjax(jsonInfo, request, response);
        }
        model.addAttribute("e", jsonInfo);
        logger.info("请求异常：" + e.getMessage(), e);
        return "error";
    }

    /**
     * 500 - Internal Server Error
     */
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public String handleException(
            Exception e,
            HttpServletResponse response,
            HttpServletRequest request,
            Model model
    ) {
        // logger.error("服务运行异常", e);
        JsonInfo jsonInfo = new JsonInfo(-1, e.getMessage());
        if (HttpUtils.isAjaxRequestInternal(request)) {
            HttpUtils.sendJsonResultByCheckAjax(jsonInfo, request, response);
        }
        model.addAttribute("e", jsonInfo);
        logger.info("请求异常：" + e.getMessage(), e);
        return "error";
    }
}
